package com.example.webrtcrooma.connection;

import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Log;


import com.example.webrtcrooma.ChatRoomActivity;
import com.example.webrtcrooma.webrtc.socket.WebRtcSocketManager;


import org.webrtc.AudioDecoderFactoryFactory;
import org.webrtc.AudioEncoderFactoryFactory;
import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.Camera1Enumerator;
import org.webrtc.Camera2Enumerator;
import org.webrtc.CameraEnumerator;
import org.webrtc.DataChannel;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoDecoderFactory;
import org.webrtc.VideoEncoderFactory;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
import org.webrtc.audio.JavaAudioDeviceModule;

import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PeerConnectionManager {
    //摄像头数据 camera2
    //音频源的获取 audioTrack
    private String myId;
    private boolean isVideoEnable;
    private ExecutorService executorService;
    private PeerConnectionFactory factory;
    private ChatRoomActivity activity;
    private EglBase eglBase;
    private Map<String, Peer> connectionPeerDic;
    private MediaStream mediaStream;
    private ArrayList<String> connectionIdArray;
    private ArrayList<PeerConnection.IceServer> iceServers = new ArrayList<>();
    private WebRtcSocketManager webRtcSocketManager;
    private String socketId;


    public PeerConnectionManager(){
        executorService = Executors.newSingleThreadExecutor();
        connectionIdArray = new ArrayList<>();
        PeerConnection.IceServer iceServer = PeerConnection.IceServer.builder("stun:8.210.234.39:3478?transport=udp")
                .setUsername("").setPassword("").createIceServer();
        iceServers.add(iceServer);
    }

    public void joinRoom(WebRtcSocketManager webRtcSocketManager, ArrayList<String> connections, boolean isVideoEnable, String myId){
        this.isVideoEnable = isVideoEnable;
        this.webRtcSocketManager = webRtcSocketManager;
        this.connectionIdArray.addAll(connections);
        this.myId = myId;
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                //本地预览
                if(factory == null) {
                    factory = createConnectionFactory();
                }
                //添加总流

//                    MediaCodec mediaCodec = MediaCodec.createDecoderByType();
//                    MediaFormat mediaFormat = new MediaFormat();
//                    mediaCodec.configure();

                if(mediaStream == null){
                    createLocalStream();
                }
                createPeerConnections();
                createOffers();
            }
        });
    }

    private void createOffers() {
        for (Map.Entry<String, Peer> entry : connectionPeerDic.entrySet()){
            Peer mPeer = entry.getValue();
            mPeer.pc.createOffer(mPeer,offerAnswerConstraint());
        }
    }

    private MediaConstraints offerAnswerConstraint() {
        MediaConstraints mediaConstraints = new MediaConstraints();
        ArrayList<MediaConstraints.KeyValuePair> keyValuePairs = new ArrayList<>();
        keyValuePairs.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
        keyValuePairs.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", String.valueOf(isVideoEnable)));
        mediaConstraints.mandatory.addAll(keyValuePairs);
        return mediaConstraints;
    }

    private void createPeerConnections() {
        for(String str : connectionIdArray){
            Peer peer = new Peer(str);
            connectionPeerDic.put(str,peer);
        }
    }

    public void onReceiverAnswer(String socketId, String sdp){
        //耗時操作
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                Peer mPeer = connectionPeerDic.get(socketId);
                SessionDescription description = new SessionDescription(SessionDescription.Type.ANSWER,sdp);
                mPeer.pc.setRemoteDescription(mPeer,description);
            }
        });

    }

    public void onRemoteIceCandidate(String socketId, IceCandidate iceCandidate) {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                Peer peer = connectionPeerDic.get(socketId);
                if (peer != null){
                    peer.pc.addIceCandidate(iceCandidate);
                }
            }
        });
    }

    public void onRemoteJoinToRoom(String socketId) {
        executorService.execute(() -> {
            if (mediaStream == null) {
                createLocalStream();
            }
            Peer mPeer = new Peer(socketId);
            mPeer.pc.addStream(mediaStream);
            connectionIdArray.add(socketId);
            connectionPeerDic.put(socketId, mPeer);
        });
    }

    public void onRemoteOutRoom(String socketId) {
        executorService.execute(() -> closePeerConnection(socketId));
    }
    // 关闭通道流
    private void closePeerConnection(String connectionId) {
        Peer mPeer = connectionPeerDic.get(connectionId);
        if (mPeer != null) {
            mPeer.pc.close();
        }
        connectionPeerDic.remove(connectionId);
        connectionIdArray.remove(connectionId);
        if (activity != null) {
            activity.onCloseWithId(connectionId);
        }

    }
    private class Peer implements SdpObserver, PeerConnection.Observer{
        private PeerConnection pc;
        private String userId;
        public Peer(String userId){
            this.userId = userId;
            pc = createPeerConnection();
        }

        @Override
        public void onCreateSuccess(SessionDescription sessionDescription) {
            Log.e("returnSuccess","asdas");
            //设置本地sdp
            pc.setLocalDescription(Peer.this,sessionDescription);
            //以及设置远端
            pc.setRemoteDescription(Peer.this,sessionDescription);
        }

        @Override
        public void onSetSuccess() {
            //管道是否连接远端客户端
            //只设置本地为主叫  call  被叫  answer
            if (pc.signalingState() == PeerConnection.SignalingState.HAVE_LOCAL_PRANSWER) {
                webRtcSocketManager.sendOffer(userId,pc.getLocalDescription().description);
            } else if (pc.signalingState() == PeerConnection.SignalingState.HAVE_REMOTE_OFFER) {
                pc.createAnswer(Peer.this, offerAnswerConstraint());
            } else  if (pc.signalingState() == PeerConnection.SignalingState.STABLE) {
                pc.createAnswer(Peer.this, offerAnswerConstraint());
            }

        }

        @Override
        public void onCreateFailure(String s) {

        }

        @Override
        public void onSetFailure(String s) {

        }
        @Override
        public void onSignalingChange(PeerConnection.SignalingState signalingState) {

        }

        @Override
        public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {

        }

        @Override
        public void onIceConnectionReceivingChange(boolean b) {

        }

        @Override
        public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {

        }

        @Override  //指揮客戶端進行請求
        public void onIceCandidate(IceCandidate iceCandidate) {
            webRtcSocketManager.sendIceCandidate(userId,iceCandidate);
        }

        @Override
        public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {

        }

        @Override
        public void onAddStream(MediaStream mediaStream) {
            //ice交換玩后回調該方法
            activity.onSetRemoteStream(mediaStream, userId);
        }

        @Override
        public void onRemoveStream(MediaStream mediaStream) {

        }

        @Override
        public void onDataChannel(DataChannel dataChannel) {

        }

        @Override
        public void onRenegotiationNeeded() {

        }

        @Override
        public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {

        }
        private PeerConnection createPeerConnection() {
            if (factory == null){
                factory = createConnectionFactory();
            }
            PeerConnection.RTCConfiguration rtcConfiguration = new PeerConnection.RTCConfiguration(iceServers);
            return factory.createPeerConnection(rtcConfiguration, this);
        }
    }



    private void createLocalStream() {
        mediaStream = factory.createLocalMediaStream("ARDAMS");
        AudioSource audioSource = factory.createAudioSource(createAudioConstraints());
        AudioTrack audioTrack = factory.createAudioTrack( "ARDAMSa0",audioSource);
        mediaStream.addTrack(audioTrack);
        if(isVideoEnable) {

            //视频源  摄像头的捕获设备
            VideoCapturer videoCapturer = createVideoCapturer();
            VideoSource videoSource = factory.createVideoSource(videoCapturer.isScreencast());
            SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", eglBase.getEglBaseContext());
            videoCapturer.initialize(surfaceTextureHelper, activity, videoSource.getCapturerObserver());
            videoCapturer.startCapture(320, 380, 10); //宽 高 关键帧

            VideoTrack videoTrack = factory.createVideoTrack("ARDAMSv0", videoSource);
            mediaStream.addTrack(videoTrack);
            if (activity != null) {
                activity.onSetLocalStream(mediaStream, myId);
            }
        }
    }

    private VideoCapturer createVideoCapturer() {
        VideoCapturer videoCapturer = null;
        if(Camera2Enumerator.isSupported(activity)){
            Camera2Enumerator camera2Enumerator = new Camera2Enumerator(activity);
            videoCapturer = createCameraCapturer(camera2Enumerator);
        }else {
            Camera1Enumerator camera1Enumerator = new Camera1Enumerator(true);
            videoCapturer = createCameraCapturer(camera1Enumerator);
        }
        return videoCapturer;
    }
// 获取前置摄像头 否则使用后置
    private VideoCapturer createCameraCapturer(CameraEnumerator camera2Enumerator) {
        String[] devicesName = camera2Enumerator.getDeviceNames();
        for(String deviceName : devicesName){
            if(camera2Enumerator.isFrontFacing(deviceName)){
                VideoCapturer videoCapturer = camera2Enumerator.createCapturer(deviceName,null);
                if(videoCapturer != null){
                    return videoCapturer;
                }
            }
        }
        for(String deviceName : devicesName){
            if(!camera2Enumerator.isFrontFacing(deviceName)){
                VideoCapturer videoCapturer = camera2Enumerator.createCapturer(deviceName,null);
                if(videoCapturer != null){
                    return videoCapturer;
                }
            }
        }

        return null;
    }

    //**************************************各种约束******************************************/
    private static final String AUDIO_ECHO_CANCELLATION_CONSTRAINT = "googEchoCancellation";
    private static final String AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT = "googAutoGainControl";
    private static final String AUDIO_HIGH_PASS_FILTER_CONSTRAINT = "googHighpassFilter";
    private static final String AUDIO_NOISE_SUPPRESSION_CONSTRAINT = "googNoiseSuppression";
    private MediaConstraints createAudioConstraints() {
        MediaConstraints mediaConstraints = new MediaConstraints();
        MediaConstraints audioConstraints = new MediaConstraints();
        audioConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(AUDIO_ECHO_CANCELLATION_CONSTRAINT, "true"));
        audioConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT, "false"));
        audioConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(AUDIO_HIGH_PASS_FILTER_CONSTRAINT, "true"));
        audioConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(AUDIO_NOISE_SUPPRESSION_CONSTRAINT, "true"));
        return audioConstraints;
    }

    private PeerConnectionFactory createConnectionFactory() {
        //编码  解码  (音视频)
        PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(activity).createInitializationOptions());
        VideoEncoderFactory videoEncoderFactory = new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(),true, true);
        VideoDecoderFactory videoDecoderFactory = new DefaultVideoDecoderFactory(eglBase.getEglBaseContext());
        PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();

//        AudioEncoderFactoryFactory audioEncoderFactoryFactory;
//        AudioDecoderFactoryFactory audioDecoderFactoryFactory;

        return PeerConnectionFactory.builder().setOptions(options)
                .setAudioDeviceModule(JavaAudioDeviceModule.builder(activity).createAudioDeviceModule())
                .setVideoDecoderFactory(videoDecoderFactory)
                .setVideoEncoderFactory(videoEncoderFactory)
                .createPeerConnectionFactory();
    }

    public void initContext(ChatRoomActivity activity, EglBase eglBase) {
        this.activity = activity;
        this.eglBase = eglBase;
    }

}



